import { getOBSConfig, setOBSConfig } from '@/services/OsSerivce';
import { relaunch } from '@/services/SystemSerivce';
import {
  DeviceType,
  DisableType,
  InputSourceConfig,
  OBSConfig,
  OutputSourceConfig,
  PTZControlType,
  SettingsData,
  SoftType,
} from '@/types';
import { MenuOutlined } from '@ant-design/icons';
import ProForm, {
  ProFormDependency,
  ProFormInstance,
  ProFormSelect,
  ProFormText,
} from '@ant-design/pro-form';
import { EditableProTable, ProColumns } from '@ant-design/pro-table';
import { Button, Modal, Tabs, message } from 'antd';
import React, { useRef, useState } from 'react';
import {
  SortableContainer,
  SortableElement,
  SortableHandle,
} from 'react-sortable-hoc';
import { useModel, useRequest } from 'umi';
import { isNotBlank } from 'web-plugin-utils';
import styles from './index.less';

const DragHandle = SortableHandle(() => (
  <MenuOutlined style={{ cursor: 'grab', color: '#999' }} />
));
function arrayMoveMutable(array: any[], fromIndex: number, toIndex: number) {
  const startIndex = fromIndex < 0 ? array.length + fromIndex : fromIndex;
  if (startIndex >= 0 && startIndex < array.length) {
    const endIndex = toIndex < 0 ? array.length + toIndex : toIndex;
    const [item] = array.splice(fromIndex, 1);
    array.splice(endIndex, 0, item);
  }
}
function arrayMoveImmutable(array: any[], fromIndex: number, toIndex: number) {
  const newArray = [...array];
  arrayMoveMutable(newArray, fromIndex, toIndex);
  return newArray;
}

const Settings = () => {
  const [_modal, contextHolder1] = Modal.useModal();
  const [_message, contextHolder2] = message.useMessage();
  const [editableKeys, setEditableRowKeys] = useState<React.Key[]>([]);
  const [isModalOpen, setIsModelOpen] = useState(false);
  const [settingsData, setSettingsData] = useState<any>();
  const { initialState, setInitialState } = useModel('@@initialState');

  const { videoMatrixServer } = useModel('global');

  const {
    inputSourceConfigs,
    updateInputSourceConfig,
    updateInputSourceConfigs,
  } = useModel('inputSource');
  const {
    outputSourceConfigs,
    updateOutputSourceConfig,
    updateOutputSourceConfigs,
  } = useModel('outputSource');

  //obs配置
  const { data: obsConfig } = useRequest<any>(() =>
    getOBSConfig(videoMatrixServer),
  );

  //修改obs配置设置
  const onOBSConfigSubmit = async (data: OBSConfig) => {
    await setOBSConfig(videoMatrixServer, data);
    _modal.confirm({
      centered: true,
      content: '设置成功，重启视频矩阵后生效',
      okText: '重启',
      cancelText: '取消',
      onOk() {
        relaunch(videoMatrixServer!);
        _message.success('重启中，请一分钟之后再试');
      },
    });
  };

  const SortableItem = SortableElement((props: any) => <tr {...props} />);
  const SortContainer = SortableContainer((props: any) => <tbody {...props} />);

  const onInputDeviceSortEnd = ({
    oldIndex,
    newIndex,
  }: {
    oldIndex: number;
    newIndex: number;
  }) => {
    if (oldIndex !== newIndex) {
      const newData = arrayMoveImmutable(
        inputSourceConfigs,
        oldIndex,
        newIndex,
      ).filter((el) => !!el);
      updateInputSourceConfigs(newData);
    }
  };

  const onOutputDeviceSortEnd = ({
    oldIndex,
    newIndex,
  }: {
    oldIndex: number;
    newIndex: number;
  }) => {
    if (oldIndex !== newIndex) {
      const newData = arrayMoveImmutable(
        outputSourceConfigs,
        oldIndex,
        newIndex,
      ).filter((el) => !!el);

      updateOutputSourceConfigs(newData);
    }
  };

  const InputDeviceDraggableContainer = (props: any) => (
    <SortContainer
      useDragHandle
      disableAutoscroll
      helperClass="row-dragging"
      onSortEnd={onInputDeviceSortEnd}
      {...props}
    />
  );

  const InputDeviceDraggableBodyRow = (props: any) => {
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    const { className, style, ...restProps } = props;
    // function findIndex base on Table rowKey props and should always be a right array index
    const index = inputSourceConfigs.findIndex(
      (x: InputSourceConfig) => x.workerName === restProps['data-row-key'],
    );

    return <SortableItem index={index} {...restProps} />;
  };

  const OutputDeviceDraggableContainer = (props: any) => (
    <SortContainer
      useDragHandle
      disableAutoscroll
      helperClass="row-dragging"
      onSortEnd={onOutputDeviceSortEnd}
      {...props}
    />
  );

  const OutputDeviceDraggableBodyRow = (props: any) => {
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    const { className, style, ...restProps } = props;
    // function findIndex base on Table rowKey props and should always be a right array index
    const index = outputSourceConfigs.findIndex(
      (x: OutputSourceConfig) => x.workerName === restProps['data-row-key'],
    );

    return <SortableItem index={index} {...restProps} />;
  };

  const inputDeviceColumns: ProColumns<InputSourceConfig>[] = [
    {
      title: '排序',
      dataIndex: 'sort',
      width: 60,
      className: 'drag-visible',
      editable: false,
      render: () => <DragHandle />,
    },
    {
      title: '输入源名称',
      dataIndex: 'name',
      editable: false,
      width: '200px',
    },
    {
      title: '设备名称',
      dataIndex: 'label',
      width: '200px',
    },
    // {
    //   title: '设备类型',
    //   width: '100px',
    //   dataIndex: 'deviceType',
    //   valueType: 'select',
    //   valueEnum: {
    //     [DeviceType.MediaInput]: {
    //       text: '媒体输入',
    //     },
    //     [DeviceType.VideoCamera]: {
    //       text: '摄像机输入',
    //     },
    //     [DeviceType.ConferenceInput]: {
    //       text: '会议输入',
    //     },
    //   },
    // },
    {
      title: '摄像机控制',
      width: '100px',
      dataIndex: 'pTZControl',
      valueType: 'select',
      valueEnum: {
        [PTZControlType.None]: {
          text: '无',
        },
        [PTZControlType.PANORAMIC_CAMERA]: {
          text: '全景摄像机',
        },
        [PTZControlType.FIELD_CAMERA]: {
          text: '术野摄像机',
        },
      },
    },
    {
      title: 'IP',
      width: '100px',
      formItemProps: {
        rules: [
          {
            message: '请输入正确的IP',
            pattern:
              /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/,
          },
        ],
      },
      dataIndex: 'remoteControlIp',
    },
    {
      title: '用户名',
      width: '100px',
      fieldProps: {
        maxLength: 50,
      },
      // formItemProps: {
      //   rules: [
      //     {
      //       required: true,
      //       message: '用户名不能为空',
      //     },
      //   ],
      // },
      dataIndex: 'remoteControlUsername',
    },
    {
      title: '密码',
      width: '100px',
      fieldProps: {
        maxLength: 50,
      },
      // formItemProps: {
      //   rules: [
      //     {
      //       required: true,
      //       message: '密码不能为空',
      //     },
      //   ],
      // },
      dataIndex: 'remoteControlPassword',
    },
    {
      title: '是否启用',
      width: '100px',
      dataIndex: 'disabled',
      valueType: 'select',
      valueEnum: {
        [DisableType.On]: {
          text: '已禁用',
          status: 'Error',
        },
        [DisableType.Off]: {
          text: '已启用',
          status: 'Success',
        },
      },
    },
    {
      title: '操作',
      valueType: 'option',
      width: '80px',
      render: (text, record, _, action) => [
        <a
          key="editable"
          onClick={() => {
            action?.startEditable?.(record.workerName);
          }}
        >
          编辑
        </a>,
      ],
    },
  ];

  const outputDeviceColumns: ProColumns<OutputSourceConfig>[] = [
    {
      title: '排序',
      dataIndex: 'sort',
      width: 60,
      className: 'drag-visible',
      editable: false,
      render: () => <DragHandle />,
    },
    {
      title: '显示器名称',
      dataIndex: 'name',
      editable: false,
      width: '200px',
    },
    {
      title: '设备名称',
      dataIndex: 'label',
      width: '200px',
    },
    {
      title: '分辨率',
      dataIndex: 'label',
      editable: false,
      width: '200px',
      render(_, record) {
        return `${record.width}x${record.height}`;
      },
    },
    {
      title: '设备类型',
      width: '100px',
      dataIndex: 'deviceType',
      valueType: 'select',
      valueEnum: {
        [DeviceType.MediaOutput]: {
          text: '媒体输出',
        },
        [DeviceType.StreamOutput]: {
          text: '流媒体输出',
        },
        [DeviceType.ConferenceOutput]: {
          text: '会议输出',
        },
      },
    },
    {
      title: '流媒体名称',
      width: '100px',
      dataIndex: 'streamName',
    },
    {
      title: '是否启用',
      width: '100px',
      dataIndex: 'disabled',
      valueType: 'select',
      valueEnum: {
        [DisableType.On]: {
          text: '已禁用',
          status: 'Error',
        },
        [DisableType.Off]: {
          text: '已启用',
          status: 'Success',
        },
      },
    },
    {
      title: '操作',
      valueType: 'option',
      width: '80px',
      render: (text, record, _, action) => [
        <a
          key="editable"
          onClick={() => {
            action?.startEditable?.(record.workerName);
          }}
        >
          编辑
        </a>,
      ],
    },
  ];

  const items: any[] = [
    {
      label: '基础设置',
      key: 'baseConfig',
      children: (
        <ProForm<SettingsData>
          initialValues={initialState}
          style={{ width: 350 }}
          onFinish={async (value) => {
            // console.log(value);
            console.log(value);
            if (value.softType !== initialState?.softType) {
              if (value.softType !== SoftType.ROOM_VIDEO_MATRIX) {
                delete value.videoMatrixIp;
                delete value.screenshotWorkName;
              }
              setIsModelOpen(true);
              setSettingsData(value);
            } else {
              setInitialState(value);
              localStorage.setItem('LOCAL_SETTINGS', JSON.stringify(value));
              _message.success('保存成功');
            }
            const result = await window.tm?.ipcRenderer.invoke(
              'setTeachConfig',
              value,
            );
            console.log(result);
          }}
        >
          <ProFormText
            rules={[
              {
                required: true,
                message: '请输入端点名称',
              },
            ]}
            name="nickname"
            label="端点名称"
          />
          <ProFormText
            name="serverIp"
            label="服务器IP"
            placeholder="请输入服务器IP"
            rules={[
              {
                required: true,
                message: '请输入正确的IP',
                pattern:
                  /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/,
              },
            ]}
          />

          <ProFormText
            name="m7sServerIp"
            label="m7s服务器ip"
            placeholder="请输入m7s服务器ip"
            rules={[
              {
                required: true,
                message: '请输入正确的IP',
                pattern:
                  /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/,
              },
            ]}
          />
          <ProFormText
            name="obsPushServer"
            label="obs服务器ip"
            placeholder="请输入obs服务器ip"
            rules={[
              {
                required: true,
                message: '请输入正确的IP',
                pattern:
                  /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/,
              },
            ]}
          />
          <ProFormText
            name="miniIOServer"
            label="miniIO地址"
            placeholder="请输入miniIO地址"
            rules={[
              {
                required: true,
                message: '请输入miniIO地址',
                pattern:
                  /^((\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])(?::\d+)?)?((?:(?:https?|ftp):\/\/)?(?:www\.)?([a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*\.[a-zA-Z]{2,})(?::\d{1,5})?(?:\/.*)?)?$/,
              },
            ]}
          />

          <ProFormSelect
            rules={[
              {
                required: true,
                message: '请选择设备类型',
              },
            ]}
            name="softType"
            label="设备类型"
            options={[
              {
                label: '手术间/会议室/示教室',
                value: SoftType.ROOM_VIDEO_MATRIX,
              },
              {
                label: '办公室',
                value: SoftType.ROOM,
              },
              {
                label: '其他',
                value: SoftType.OTHER,
              },
            ]}
            allowClear
          />
          <ProFormDependency name={['softType']}>
            {({ softType }) => {
              return (
                <>
                  <ProFormText
                    hidden={softType !== SoftType.ROOM_VIDEO_MATRIX}
                    name="videoMatrixIp"
                    label="视频矩阵IP"
                    placeholder="请输入视频矩阵IP"
                    rules={[
                      {
                        message: '请输入正确的IP',
                        pattern:
                          /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])(?::\d+)?$/,
                      },
                    ]}
                  />
                  <ProFormSelect
                    hidden={softType !== SoftType.ROOM_VIDEO_MATRIX}
                    // rules={[
                    //   {
                    //     required: true,
                    //     message: '请选择截图画面',
                    //   },
                    // ]}
                    name="screenshotWorkName"
                    label="截图画面"
                    options={[
                      ...(inputSourceConfigs || [])
                        .filter((c: any) => c.disabled === DisableType.Off)
                        .map((c: any) => ({
                          label: c.label,
                          value: c.workerName,
                        })),
                      ...(outputSourceConfigs || [])
                        .filter((c: any) => c.disabled === DisableType.Off)
                        .map((c: any) => ({
                          label: c.label,
                          value: c.workerName,
                        })),
                    ]}
                    allowClear
                  />
                </>
              );
            }}
          </ProFormDependency>
        </ProForm>
      ),
    },
    isNotBlank(initialState?.videoMatrixIp)
      ? {
          label: '输入设置',
          key: 'inputConfig',
          children: (
            <EditableProTable<InputSourceConfig>
              size="small"
              rowKey="workerName"
              headerTitle="输入设备"
              maxLength={5}
              columns={inputDeviceColumns}
              value={inputSourceConfigs}
              recordCreatorProps={false}
              components={{
                body: {
                  wrapper: InputDeviceDraggableContainer,
                  row: InputDeviceDraggableBodyRow,
                },
              }}
              editable={{
                type: 'multiple',
                editableKeys,
                actionRender: (row, config, defaultDoms) => {
                  return [defaultDoms.save, defaultDoms.cancel];
                },
                onSave: async (rowKey, data) => {
                  await updateInputSourceConfig(data);
                },
                onChange: setEditableRowKeys,
              }}
            />
          ),
        }
      : undefined,
    isNotBlank(initialState?.videoMatrixIp)
      ? {
          label: '输出设置',
          key: 'outputConfig',
          children: (
            <EditableProTable<OutputSourceConfig>
              rowKey="workerName"
              headerTitle="输出设备"
              maxLength={5}
              columns={outputDeviceColumns}
              value={outputSourceConfigs}
              recordCreatorProps={false}
              components={{
                body: {
                  wrapper: OutputDeviceDraggableContainer,
                  row: OutputDeviceDraggableBodyRow,
                },
              }}
              editable={{
                type: 'multiple',
                editableKeys,
                actionRender: (row, config, defaultDoms) => {
                  return [defaultDoms.save, defaultDoms.cancel];
                },
                onSave: async (rowKey, data) => {
                  await updateOutputSourceConfig(data);
                },
                onChange: setEditableRowKeys,
              }}
            />
          ),
        }
      : undefined,
  ];

  const formRef = useRef<ProFormInstance>();

  return (
    <div className={styles.main}>
      {contextHolder1}
      {contextHolder2}
      <div className={styles.content}>
        <Modal
          centered
          title="确认配置参数"
          open={isModalOpen}
          okButtonProps={{
            style: { display: 'none' },
          }}
          cancelButtonProps={{
            style: { display: 'none' },
          }}
        >
          <ProForm<{ password: string }>
            formRef={formRef}
            submitter={{
              render: (props, doms) => {
                return [
                  doms[1],
                  <Button
                    htmlType="button"
                    onClick={() => {
                      setIsModelOpen(false);
                      props.reset();
                    }}
                    key="edit"
                  >
                    取消
                  </Button>,
                ];
              },
            }}
            onFinish={async (value) => {
              if (value.password === 'bjwk1111') {
                if (settingsData) {
                  setInitialState(settingsData);
                  setSettingsData(undefined);
                  localStorage.setItem(
                    'LOCAL_SETTINGS',
                    JSON.stringify(settingsData),
                  );
                  _message.success('保存成功');
                  setIsModelOpen(false);
                  formRef.current?.resetFields();
                }
              } else {
                _message.error('密码错误');
              }
            }}
          >
            <ProFormText.Password
              name="password"
              label="密码"
              rules={[
                {
                  required: true,
                  message: '请输入密码',
                },
              ]}
            />
          </ProForm>
        </Modal>
        <Tabs tabPosition="left" className={styles.tabs} items={items} />
      </div>
    </div>
  );
};

export default Settings;
